package cn.kys.common.utils;

import com.alibaba.fastjson.JSONObject;

import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.*;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GeojsonToShape {

    public static void main(String[] args) {

        geojson2Shape( "C:\\Users\\Administrator\\Desktop\\json\\1.geojson", "C:\\Users\\Administrator\\Desktop\\json\\1.shp");

    }

    public static void geojson2Shape(String geojsonStr, String shpPath){
        GeometryJSON geojson = new GeometryJSON();
        try{
            //String geojsonStr = readJson(jsonPath);
            Map<String, Object> geojsonMap = JSONObject.parseObject(geojsonStr, Map.class);
            List<Map> features = (List<Map>) geojsonMap.get("features");
            Map geojsonExemple = features.get(0);
            String geojsonType = ((Map) geojsonExemple.get("geometry")).get("type").toString();
            Map<String, Class> mapFields = new HashMap();
            for (int i = 0; i < features.size(); i++) {
                Map<String, Object> attributes = (Map<String, Object>) features.get(i).get("properties");
                for (String key : attributes.keySet()) {
                    if (attributes.get(key)==null||attributes.get(key).equals("")){
                        mapFields.put(key, "null".getClass());
                    }else{
                        Class type = attributes.get(key).getClass();
                        mapFields.put(key, type);
                    }
                }


            }

            Class<?> geoType = null;
            switch(geojsonType){
                case "Point":
                    geoType = Point.class;
                    break;
                case "MultiPoint":
                    geoType = MultiPoint.class;
                    break;
                case "LineString":
                    geoType = LineString.class;
                    break;
                case "MultiLineString":
                    geoType = MultiLineString.class;
                    break;
                case "Polygon":
                    geoType = Polygon.class;
                    break;
                case "MultiPolygon":
                    geoType = MultiPolygon.class;
                    break;
            }

            //创建shape文件对象
            File file = new File(shpPath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put( ShapefileDataStoreFactory.URLP.key, file.toURI().toURL() );
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            ds.setCharset(Charset.forName("GBK"));
            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);
            tb.setName("shapefile");
            tb.add("the_geom", geoType);

            for (String key : mapFields.keySet()) {
                tb.add(key, mapFields.get(key));
            }

            ds.createSchema(tb.buildFeatureType());
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.
                    getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);

            for(int i=0,len=features.size();i<len;i++){
                Map oneGeojson = features.get(i);
                Map<String,Object> attributes = (Map<String, Object>) oneGeojson.get("properties");
                String strFeature = JSONObject.toJSONString(oneGeojson);
                Reader reader = new StringReader(strFeature);
                SimpleFeature feature = writer.next();

                switch(geojsonType){
                    case "Point":
                        feature.setAttribute("the_geom",geojson.readPoint(reader));
                        break;
                    case "MultiPoint":
                        feature.setAttribute("the_geom",geojson.readMultiPoint(reader));
                        break;
                    case "LineString":
                        feature.setAttribute("the_geom",geojson.readLine(reader));
                        break;
                    case "MultiLineString":
                        feature.setAttribute("the_geom",geojson.readMultiLine(reader));
                        break;
                    case "Polygon":
                        feature.setAttribute("the_geom",geojson.readPolygon(reader));
                        break;
                    case "MultiPolygon":
                        feature.setAttribute("the_geom",geojson.readMultiPolygon(reader));
                        break;
                }

                for (String key : attributes.keySet()) {
                    feature.setAttribute(key,attributes.get(key));
                }
                writer.write();
            }
            writer.close();
            ds.dispose();
        }
        catch(Exception e){
            System.out.println("转换失败");
            e.printStackTrace();
        }
    }


    /**
     * 读取文件
     * @param filepath 文件路径
     * @throws IOException
     */
    public static String readJson(String filepath) {
        FileReader re = null;
        BufferedReader buff = null;
        String line = "";
        try {
            File file = new File(filepath);
            re = new FileReader(file);
            buff = new BufferedReader(re);
            String tempString = null;
            while ((tempString = buff.readLine()) != null) {
                line += tempString;
            }
            return line;
        } catch (Exception e) {
            System.out.println("失败了");
        } finally {
            try {
                re.close();
                buff.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return line;
    }

}
